from django.views import View
from QQLoginTool.QQtool import OAuthQQ
from django.conf import settings
from django.contrib.auth import login
from django_redis import get_redis_connection
from django import http
from django.db import DatabaseError
import logging
import json
import re


from apps.oauth.models import OAUTHQQUser
from apps.oauth.utils import generator_access_token, check_access_token
from apps.users.models import User

# Create your views here.

# 创建日志生成器
logger = logging.getLogger('django')


# QQ登录的第二个接口
class QQUserView(View):
    """用户扫码登录的回调处理
    GET /oauth_callback/
    """
    def get(self, request):
        """Oauth2.0认证"""

        # 获取authorization code
        code = request.GET.get('code')
        # 校验参数
        if not code:
            return http.JsonResponse({'code': 400, 'errmsg': '缺少code参数'})

        # 创建OAuthQQ 类对象
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                        client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI)

        try:
            # 携带 code 向 QQ服务器 请求 access_token
            access_token = oauth.get_access_token(code)

            # 携带 access_token 向 QQ服务器 请求 openid
            openid = oauth.get_open_id(access_token)

        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code': 400,
                                      'errmsg': 'oauth2.0认证失败, 即获取qq信息失败'})

        # 判断登录的QQ用户是否绑定美多商城
        try:
            oauth_user = OAUTHQQUser.objects.get(openid=openid)
        # except OAUTHQQUser.DoesNotExist:
        except Exception as e:
            # logger.error(e)access_token
            access_token = generator_access_token(openid)
            # 此处的code码为300，是因为未绑定用户需要重定向到绑定页面
            return http.JsonResponse({'code': 300, 'errmsg': '用户未绑定', 'access_token': access_token})
        else:
            user = oauth_user.user
            login(request, user)
            response = http.JsonResponse({'code': 0, 'errmsg': 'ok'})
            response.set_cookie('username', user.username)
            return response

    def post(self, request):
        """绑定用户"""
        # 提取参数
        json_dict = json.loads(request.body.decode())
        mobile = json_dict.get('mobile')
        password = json_dict.get('password')
        sms_code_client = json_dict.get('sms_code')
        access_token = json_dict.get('access_token')
        # 校验参数
        if not all([mobile, password, sms_code_client]):
            return http.JsonResponse({'code': 400, 'errmsg': '缺少必传参数'})
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.JsonResponse({'code': 400, 'errmsg': 'mobile参数格式有误'})
        if not re.match(r'^[a-zA-Z0-9]{8,20}$', password):
            return http.JsonResponse({'code': 400, 'errmsg': 'password参数格式有误'})

        redis_conn = get_redis_connection('verify_code')
        sms_code_server = redis_conn.get('sms_code_%s' % mobile)

        if not sms_code_server:
            return http.JsonResponse({'code': 400, 'errmsg': '短信验证码失效'})
        if sms_code_client != sms_code_server.decode():
            return http.JsonResponse({'code': 400, 'errmsg': '短信验证码输入有误'})

        # 获取openid明码
        openid = check_access_token(access_token)
        if not openid:
            return http.JsonResponse({'code': 400, 'errmsg': '缺少openid'})

        # 判断输入的手机号是否存在
        try:
            user = User.objects.get(mobile=mobile)
        # except User.DoesNotExist:
        except Exception as e:
            logger.error(e)
            user = User.objects.create_user(username=mobile, password=password, mobile=mobile)
        else:
            if not user.check_password(password):
                return http.JsonResponse({'code': 400, 'errmsg': '输入密码有误'})

        try:
            # 绑定openid用户
            OAUTHQQUser.objects.create(user=user, openid=openid)
        except DatabaseError:
            return http.JsonResponse({'code': 400,
                                      'errmsg': '往数据库添加数据出错'})
        # 状态保持
        login(request, user)
        response = http.JsonResponse({'code': 0, 'errmsg': 'ok'})
        response.set_cookie('username', user.username)
        return response


# QQ登录第一个接口
class QQURLView(View):
    """提供QQ登录页面网址
    GET /qq/authorization/
    """
    def get(self, request):
        # next 表示从哪个页面进入到的登录页面
        # 将来登录成功后，就自动回到那个页面
        next = request.GET.get('next', '/')

        # 创建OAuthQQ 类对象
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                        client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI,
                        state=next)

        # 调用对象获取 qq 地址方法
        login_url = oauth.get_qq_url()

        # 返回登录地址
        return http.JsonResponse({'code': 0, 'errmsg': 'ok', 'login_url': login_url})


